package com.xzj.common.okhttp.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.util.Map;

/**
 * @program: xzj-common
 * @ClassName: HttpUtil
 * @description: http请求方法封装
 * @author: XiaZunJun
 * @create: 2024-07-23 14:06
 */
@Slf4j
public class HttpUtil {

    /**
     * 调用okhttp的newCall方法
     *
     * @param request 请求体
     * @return String
     */
    private static <T> T execNewCall(Request request,Class<T> tClass) {
        Response response = null;
        try {
            OkHttpClient okHttpClient = SpringUtil.getBean(OkHttpClient.class);
            response = okHttpClient.newCall(request).execute();
            log.debug("execute http response code is {}, request body is {}", response.code(),
                    HttpCommonUtil.analysisRequestBody(request.body()));
            if (response.isSuccessful()) {
                String result = response.body().string();
                return JSONObject.parseObject(result,tClass);
            }
        } catch (Exception e) {
            log.error("{} , url:{},param:{}", e.getMessage(), request.url(), HttpCommonUtil.analysisRequestBody(request.body()));
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return null;
    }

    public static <T> T get(String url,Class<T> tClass){
        return get(url,null,tClass);
    }

    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数，在浏览器？后面的数据，没有可以传null
     * @return String
     */
    public static <T> T get(String url, Map<String, String> queries,Class<T> tClass) {
        StringBuffer sb = HttpCommonUtil.getQueryString(url, queries);
        Request request = new Request.Builder().url(sb.toString()).build();
        return execNewCall(request,tClass);
    }

    public static <T> T patch(String url,String jsonBody,Class<T> tClass){
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(jsonBody, JSON);
        Request request = new Request.Builder().url(url).patch(body).build();
        return execNewCall(request,tClass);
    }

    public static <T> T delete(String url,Class<T> tClass){
        Request request = new Request.Builder().url(url).delete().build();
        return execNewCall(request,tClass);
    }

    public static <T> T upload(Request request,Class<T> tClass){
        return execNewCall(request,tClass);
    }


    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数，在浏览器？后面的数据，没有可以传null
     * @return String
     */
    public static <T> T get(String url, JSONObject queries, String header,Class<T> tClass) {
        StringBuffer sb = HttpCommonUtil.getQueryString(url, queries);
        Request request;
        if (StrUtil.isNotEmpty(header)) {
            Map<String, String> headerMap = HttpCommonUtil.convertHeader(header);
            request = new Request.Builder().url(sb.toString()).headers(Headers.of(headerMap)).build();
        } else {
            request = new Request.Builder().url(sb.toString()).build();
        }
        return execNewCall(request,tClass);
    }

    /**
     * post
     *
     * @param url    请求的url
     * @param params post form 提交的参数
     * @return String
     */
    public static <T> T postFormParams(String url, Map<String, String> params, String header,Class<T> tClass) {
        FormBody.Builder builder = new FormBody.Builder();
        //添加参数
        if (params != null && !params.keySet().isEmpty()) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request request = HttpCommonUtil.judgeHeaders(url, builder.build(), header);
        return execNewCall(request,tClass);
    }

    public static <T> T postJsonParams(String url, String jsonParams,Class<T> tClass) {
        return postJsonParams(url, jsonParams,null ,tClass);
    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一：请求Url 参数二：请求的JSON 参数三：请求回调
     */
    public static <T> T postJsonParams(String url, String jsonParams, String header,Class<T> tClass) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
        Request request = HttpCommonUtil.judgeHeaders(url, requestBody, header);
        T result = null;
        int count = 0;
        while (ObjectUtil.isEmpty(result)) {
            if (count >= 15) {
                log.error("达到最大调用次数:15,访问地址:{},请求参:{},头部信息:{}", url, jsonParams, header);
                break;
            }
            result = execNewCall(request,tClass);
            if (ObjectUtil.isEmpty(result)) {
                try {
                    count++;
                    Thread.sleep(10000L);
                    log.error("遇到接口异常，线程休眠10s，已休眠次数为:{}", count);
                } catch (InterruptedException e) {
                    log.error("线程休眠异常:{}", e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一：请求Url 参数二：请求的JSON 参数三：请求回调
     */
    public static <T> T postNotTry(String url, String jsonParams, String header,Class<T> tClass) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
        Request request = HttpCommonUtil.judgeHeaders(url, requestBody, header);
        return execNewCall(request,tClass);
    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一：请求Url 参数二：请求的JSON 参数三：请求回调
     */
    public static <T> T postNotTry(String url, String jsonParams,Class<T> tClass) {
        return postNotTry(url,jsonParams,null,tClass);
    }

    /**
     * Post请求发送xml数据.... 参数一：请求Url 参数二：请求的xmlString 参数三：请求回调
     */
    public static <T> T postXmlParams(String url, String xml, String header,Class<T> tClass) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Request request = HttpCommonUtil.judgeHeaders(url, requestBody, header);
        return execNewCall(request,tClass);
    }
}
